package org.example.aspect;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.example.service.User;
import org.example.service.UserService;
import org.example.service.UserServiceImpl;
import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.StaticMethodMatcherPointcut;

import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();

        ProxyFactory proxyFactory = new ProxyFactory();
        // 添加TargetSource
        TargetSource targetSource = getTargetSource(userService);
        proxyFactory.setTargetSource(targetSource);
        // setTarget-->底层会封装为SingletonTargetSource
//        proxyFactory.setTarget(userService);
        // 添加Advice-->底层会封装为Advisor
        proxyFactory.addAdvice(getBeforeAdvice());
        // 添加Advisor = Advice + Pointcut
        proxyFactory.addAdvisor(getAdvisor());
        // 获取代理类
        UserService userServiceProxy = (UserService)proxyFactory.getProxy();
        // 执行代理方法
        userServiceProxy.init();
    }

    private static PointcutAdvisor getAdvisor() {
        return new PointcutAdvisor() {
            @Override
            public Pointcut getPointcut() {
                return new StaticMethodMatcherPointcut() {

                    @Override
                    public boolean matches(Method method, Class<?> targetClass) {
                        // 给init方法添加切入点
                        return method.getName().equals("init");
                    }
                };
            }

            @Override
            public Advice getAdvice() {
                return new MethodInterceptor() {

                    @Override
                    public Object invoke(MethodInvocation invocation) throws Throwable {
                        System.out.println("执行方法前。。。");
                        Object proceed = invocation.proceed();
                        System.out.println("invoke.MethodName:"+invocation.getMethod().getName());
                        System.out.println("执行方法后。。。");
                        return proceed;
                    }
                };
            }

            @Override
            public boolean isPerInstance() {
                return false;
            }
        };
    }

    private static MethodInterceptor getBeforeAdvice() {
        return new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("执行方法前处理。。。");
                return invocation.proceed();
            }
        };
    }

    private static TargetSource getTargetSource(Object target) {
        TargetSource targetSource = new TargetSource() {
            @Override
            public Class<?> getTargetClass() {
                return UserService.class;
            }

            @Override
            public boolean isStatic() {
                return true;
            }

            @Override
            public Object getTarget() throws Exception {
                return target;
            }

            @Override
            public void releaseTarget(Object target) throws Exception {

            }
        };
        return targetSource;
    }
}
